package org.finesys.common.database.core.config;

import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import org.finesys.common.database.core.constants.DataSourceConstants;
import org.finesys.common.database.core.properties.FineDataSourceProperties;
import org.jasypt.encryption.StringEncryptor;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

/**
 * * 数据源来源的默认实现是YmlDynamicDataSourceProvider，其从yaml或properties中读取信息并解析出所有数据源信息。
 * * 我们继承AbstractJdbcDataSourceProvider从数据源中获取配置信息
 * * 从3.4.0开始，可以注入多个DynamicDataSourceProvider的Bean以实现同时从多个不同来源加载数据源，注意同名会被覆盖。
 */
public class JdbcDynamicDataSourceProvider extends AbstractJdbcDataSourceProvider {
    private final FineDataSourceProperties properties;

    private final StringEncryptor stringEncryptor;

    public JdbcDynamicDataSourceProvider(DefaultDataSourceCreator defaultDataSourceCreator, StringEncryptor stringEncryptor, FineDataSourceProperties dataSourceProperties) {
        //String driverClassName, String url, String username, String password
        super(dataSourceProperties.getDriverClassName(), dataSourceProperties.getUrl(), dataSourceProperties.getUsername(), dataSourceProperties.getPassword());
        this.stringEncryptor = stringEncryptor;
        this.properties = dataSourceProperties;
    }

    /**
     * 执行语句获得数据源参数
     *
     * @param statement 语句
     * @return 数据源参数
     * @throws SQLException sql异常
     */
    @Override
    protected Map<String, DataSourceProperty> executeStmt(Statement statement) throws SQLException {
        ResultSet rs = statement.executeQuery(properties.getQueryDsSql());
        Map<String, DataSourceProperty> map = new HashMap<>();
        while (rs.next()) {
            String name = rs.getString(DataSourceConstants.DS_NAME);
            String username = rs.getString(DataSourceConstants.DS_USER_NAME);
            String password = rs.getString(DataSourceConstants.DS_USER_PWD);
            String url = rs.getString(DataSourceConstants.DS_JDBC_URL);
            String driverClassName = rs.getString(DataSourceConstants.DS_DRIVER_CLASS_NAME);
            DataSourceProperty dataSourceProperty = new DataSourceProperty();
            dataSourceProperty.setDriverClassName(driverClassName);
            dataSourceProperty.setUrl(url);
            dataSourceProperty.setUsername(username);
            dataSourceProperty.setLazy(true);
            try {
                dataSourceProperty.setPassword(stringEncryptor.decrypt(password));
            } catch (Exception e) {
                dataSourceProperty.setPassword(password);
            }
            map.put(name, dataSourceProperty);
        }
        //添加默认主数据源
        DataSourceProperty property = new DataSourceProperty();
        property.setUsername(properties.getUsername());
        property.setPassword(properties.getPassword());
        property.setUrl(properties.getUrl());
        property.setDriverClassName(properties.getDriverClassName());
        property.setLazy(false);
        map.put(DataSourceConstants.DS_MASTER, property);
        return map;
    }
}
